package tk.heimashuma.store.service.impl;

import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.MatchPhraseQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;
import tk.heimashuma.store.entity.Commodity;
import tk.heimashuma.store.entity.CommodityType;
import tk.heimashuma.store.entity.es.EsCommodity;
import tk.heimashuma.store.entity.vo.PagingVo;
import tk.heimashuma.store.repository.CommodityRepository;
import tk.heimashuma.store.repository.CommodityTypeReposity;
import tk.heimashuma.store.repository.es.EsCommodityRepository;
import tk.heimashuma.store.service.CommodityService;
import tk.heimashuma.store.utils.RedisUtil;

import java.util.*;

@Service
public class CommodityServiceImpl implements CommodityService {
    @Autowired
    private CommodityRepository commodityRepository;
    @Autowired
    private EsCommodityRepository esCommodityRepository;
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    @Autowired
    private CommodityTypeReposity commodityTypeReposity;
    @Autowired
    private RedisUtil redisUtil;

    @Override
    public AggregatedPage<EsCommodity> commodityListSearchByEs(String keyword, Integer page, Integer size) {
        // 设置高亮的标签
        String preTag = "<em>";
        String postTag = "</em>";
        Pageable pageable =  PageRequest.of(page,size);
        SearchQuery searchQuery = null;
        if(keyword != ""){
            searchQuery = new NativeSearchQueryBuilder().
                    withQuery(QueryBuilders.matchQuery("title", keyword)).
                    withHighlightFields(new HighlightBuilder.Field("title").preTags(preTag).postTags(postTag)).build();
        }else{
            searchQuery = new NativeSearchQueryBuilder().build();
        }

        searchQuery.setPageable(pageable);

        searchQuery.setPageable(pageable);
        AggregatedPage<EsCommodity> esCommodities = getEsCommodities(searchQuery);

        return esCommodities;
    }

    private AggregatedPage<EsCommodity> getEsCommodities(SearchQuery searchQuery) {
        return elasticsearchTemplate.queryForPage(searchQuery, EsCommodity.class,
                    new SearchResultMapper() {
                @Override
                public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
                    List<EsCommodity> chunk = new ArrayList<>();
                    long total = searchResponse.getHits().getTotalHits();
                    for(SearchHit hit : searchResponse.getHits()){
                        if(searchResponse.getHits().getHits().length <= 0){
                            return null;
                        }
                        EsCommodity esCommodity = new EsCommodity();
                        esCommodity.setId(hit.getId());
                        esCommodity.setScore(hit.getScore());
                        Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                        esCommodity.setPrice(Float.valueOf(String.valueOf(sourceAsMap.get("price"))));
                        esCommodity.setType_id(Integer.valueOf(String.valueOf(sourceAsMap.get("type_id"))));
                        esCommodity.setImages(String.valueOf(sourceAsMap.get("images")));
                        esCommodity.setSales_volume(Long.valueOf(String.valueOf(sourceAsMap.get("sales_volume"))));
                        esCommodity.setRepertory(Long.valueOf(String.valueOf(sourceAsMap.get("repertory"))));
                        esCommodity.setCid(Long.valueOf(String.valueOf(sourceAsMap.get("cid"))));
                        esCommodity.setTitle(String.valueOf(sourceAsMap.get("title")));
                        // 拿到高亮
                        HighlightField highlightField = hit.getHighlightFields().get("title");
                        // 设置属性
                        if (highlightField != null) {
                            esCommodity.setTitle(highlightField.fragments()[0].toString());
                        }
                        chunk.add(esCommodity);

                    }
                    if (chunk.size() > 0) {
                        return new AggregatedPageImpl<>((List<T>) chunk,total);
                    }
                    return null;
                }
            });
    }

    @Override
    @Cacheable(key = "#root.methodName",value = "childAllType")
    public List<CommodityType> getAllCommodityType() {
        List<CommodityType> allTname = commodityTypeReposity.findAllTname();
        return allTname;
    }

    @Override
    public AggregatedPage<EsCommodity> commodityListSearchByEs(String keyword, Integer page, Integer size, Integer type) {
        String preTag = "<em>";
        String postTag = "</em>";
        Pageable pageable =  PageRequest.of(page,size);
        SearchQuery searchQuery = null;
        TermQueryBuilder typeQuery = QueryBuilders.termQuery("type_id",type);
        if(keyword != ""){
            MatchQueryBuilder title = QueryBuilders.matchQuery("title", keyword);
            searchQuery = new NativeSearchQueryBuilder().
                    withQuery(QueryBuilders.boolQuery().must(title).must(typeQuery))
                    .withHighlightFields(new HighlightBuilder.Field("title").preTags(preTag).postTags(postTag)).build();
        }else{
            searchQuery = new NativeSearchQueryBuilder().withQuery(typeQuery).build();
        }
        searchQuery.setPageable(pageable);
        searchQuery.setPageable(pageable);
        AggregatedPage<EsCommodity> esCommodities = getEsCommodities(searchQuery);
        return esCommodities;
    }

    @Override
    public void saveHotWordToRedis(String keyword) {
        redisUtil.sSetAndTime("keyword",10000,keyword);
    }

    @Override
    public Set<String> getHotWordByRedis() {
        Set<String> set = redisUtil.sGet("keyword");
        return set;
    }

    @Override
    public PagingVo commodityAllList(PagingVo pagingVo) {
//        PageRequest pageRequest = new PageRequest(pagingVo.getPage()-1,pagingVo.getPage()*9);
        //PageRequest of = PageRequest.of((pagingVo.getPage() - 1) * pagingVo.getPageSize(), pagingVo.getPageSize());
        PageRequest of = PageRequest.of(pagingVo.getPage(), pagingVo.getPageSize());
        Page<Commodity> pageList = commodityRepository.findAll(of);
        List<Commodity> content = pageList.getContent();
        for(Commodity c :content){
            c.setTransactionList(null);
            c.setImagesList(null);
            c.setTransactionCommodityCars(null);
        }
        pagingVo.setState(200);
        pagingVo.setCommodities(content);
        return pagingVo;
    }
    @Override
    public List<EsCommodity> commodityListByEs(String keyword){
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchQuery("title", keyword))
                .build();
        List<EsCommodity> esCommodities = elasticsearchTemplate.queryForList(searchQuery,EsCommodity.class);
        return esCommodities;
    }

    @Override
    public PagingVo countCommodityNum(PagingVo pagingVo) {
        pagingVo.setCount(commodityRepository.count());
        return pagingVo;
    }

    @Override
    public Optional<Commodity> findCommodity_infoById(Integer id) {
        Optional<Commodity> commodityOpt = commodityRepository.findById(id);
        return commodityOpt;
    }

    @Override
    @Cacheable(key = "caches[0].name",value = {"commodityType"})
    public List<CommodityType> findCommodityTypeFirst() {
        List<CommodityType> commodityTop = commodityTypeReposity.findCommodityTypeFirst();
        return commodityTop;
    }

    @Override
    @Cacheable(key = "args[0]",value={"childType"})
    //@CacheEvict(value = "commodityType",allEntries = true)
    public List<CommodityType> findCommodityTypeChildByName(String type) {
        Integer firstId = commodityTypeReposity.findIdByTname(type);
        if(Optional.ofNullable(firstId).isPresent()){
            List<CommodityType> typeList = commodityTypeReposity.findTnameByDescription(firstId);
            return typeList;
        }
        return null;
    }




}
